#include "SampleWindow.h"

#include <QtGui>
#include <iostream>
#include "NewParameters.h"

SampleWindow::SampleWindow()
{
  QDoubleValidator *sci =  new QDoubleValidator();

  QComboBox *nbLayer = new QComboBox();
  nbLayer->addItem("1");
  nbLayer->addItem("2");
  nbLayer->addItem("3");
  nbLayer->setCurrentIndex(1);

  QVBoxLayout *layersLayout = new QVBoxLayout();
  layer1 = new QRadioButton("Layer 1");
  layer2 = new QRadioButton("Layer 2");
  layer3 = new QRadioButton("Layer 3");
  layer3->setDisabled(true);
  layersLayout->addWidget(layer1);
  layersLayout->addWidget(layer2);
  layersLayout->addWidget(layer3);

  QGroupBox *materialBox = new QGroupBox("Material");
  QFormLayout *materialLayout = new QFormLayout();
  ms = new QLineEdit();
  ms->setValidator(sci);
  ms->setToolTip("saturation magnetization in Amps/metres");
  k = new QLineEdit();
  k->setValidator(sci);
  k->setToolTip("anisotropy constant in Joules/cubic metres");
  kPhi = new QDoubleSpinBox();
  kPhi->setToolTip("angle with the y axis in degrees");
  kTheta = new QDoubleSpinBox();
  kTheta->setToolTip("angle with the z axis in degrees");
  alpha = new QDoubleSpinBox();
  alpha->setToolTip("damping");
  materialLayout->addRow("Ms=",ms);
  materialLayout->addRow("alpha=",alpha);
  materialLayout->addRow("K=",k);
  materialLayout->addRow("theta=",kTheta);
  materialLayout->addRow("phi=",kPhi);
  materialBox->setLayout(materialLayout);

  QGroupBox *geometryBox = new QGroupBox("Geometry");
  QFormLayout *geometryLayout = new QFormLayout();
  surface = new QLineEdit();
  surface->setValidator(sci);
  surface->setToolTip("surface of the layer in square meters");
  thickness = new QLineEdit();
  thickness->setValidator(sci);
  thickness->setToolTip("thickness of the layer in meters");
  geometryLayout->addRow("surface=",surface);
  geometryLayout->addRow("thickness",thickness);
  geometryBox->setLayout(geometryLayout);

  QGroupBox *exchangeBox = new QGroupBox("Exchange");
  QFormLayout *exchangeLayout = new QFormLayout();
  upExchange = new QLineEdit();
  upExchange->setValidator(sci);
  upExchange->setToolTip("exchange constant with the upper layer");
  downExchange = new QLineEdit();
  downExchange->setValidator(sci);
  downExchange->setToolTip("exchange constant with the lower layer");
  exchangeLayout->addRow("upExchange",upExchange);
  exchangeLayout->addRow("downExchange",downExchange);
  exchangeBox->setLayout(exchangeLayout);

  QGroupBox *demagnetizationBox = new QGroupBox("Demagnetization");
  QHBoxLayout *demagHBox = new QHBoxLayout();
  QVBoxLayout *selfBox = new QVBoxLayout();
  QLabel *selfLabel = new QLabel("self");
  selfX = new QDoubleSpinBox();
  selfY = new QDoubleSpinBox();
  selfZ = new QDoubleSpinBox();
  QFormLayout *selfLayout = new QFormLayout();
  selfLayout->addRow("x",selfX);
  selfLayout->addRow("y",selfY);
  selfLayout->addRow("z",selfZ);
  selfBox->addWidget(selfLabel);
  selfBox->addLayout(selfLayout);
  demagHBox->addLayout(selfBox);
  QVBoxLayout *mutualBox = new QVBoxLayout();
  QLabel *mutualLabel = new QLabel("mutual");
  mutualX = new QDoubleSpinBox();
  mutualY = new QDoubleSpinBox();
  mutualZ = new QDoubleSpinBox();
  QFormLayout *mutualLayout = new QFormLayout();
  mutualLayout->addRow("x",mutualX);
  mutualLayout->addRow("y",mutualY);
  mutualLayout->addRow("z",mutualZ);
  mutualBox->addWidget(mutualLabel);
  mutualBox->addLayout(mutualLayout);
  demagHBox->addLayout(selfBox);
  demagHBox->addLayout(mutualBox);
  demagnetizationBox->setLayout(demagHBox);

  QGroupBox *magnetizationBox = new QGroupBox("Magnetization");
  QFormLayout *magLayout = new QFormLayout();
  frozen = new QCheckBox();
  frozen->setToolTip("check if the magnetization doesn't change during the calculation");
  mx = new QDoubleSpinBox();
  my = new QDoubleSpinBox();
  mz = new QDoubleSpinBox();
  initialAngle = new QDoubleSpinBox();
  initialAngle->setRange(0,180);
  initialAngle->setToolTip("angle with the initial position in degrees");
  magLayout->addRow("frozen",frozen);
  magLayout->addRow("mx=",mx);
  magLayout->addRow("my=",my);
  magLayout->addRow("mz=",mz);
  magLayout->addRow("initial Angle=",initialAngle);
  magnetizationBox->setLayout(magLayout);

  QGroupBox *polBox = new QGroupBox("Polarization");
  QVBoxLayout *polLayout = new QVBoxLayout();
  polType = new QComboBox();
  polType->addItem("Slonczewski");
  polType->addItem("Xiao");
  polLayout->addWidget(polType);
  polWidget = new QStackedWidget();
  QFormLayout * sloncLayout = new QFormLayout();
  polarization = new QDoubleSpinBox();
  polarization->setRange(0,1);
  sloncLayout->addRow("polarization",polarization);
  QWidget *sloncWidget = new QWidget();
  sloncWidget->setLayout(sloncLayout);
  polWidget->addWidget(sloncWidget);
  QHBoxLayout *xiaoLayout = new QHBoxLayout();
  QFormLayout *qLayout = new QFormLayout();
  QFormLayout *bLayout = new QFormLayout();
  qplus = new QDoubleSpinBox();
  qminus = new QDoubleSpinBox();
  b0 = new QDoubleSpinBox();
  b1 = new QDoubleSpinBox();
  qLayout->addRow("q+",qplus);
  qLayout->addRow("q-",qminus);
  bLayout->addRow("b0",b0);
  bLayout->addRow("b1",b1);
  xiaoLayout->addLayout(qLayout);
  xiaoLayout->addLayout(bLayout);
  QWidget *xiaoWidget = new QWidget();
  xiaoWidget->setLayout(xiaoLayout);
  polWidget->addWidget(xiaoWidget);
  polLayout->addWidget(polWidget);
  polLayout->setAlignment(Qt::AlignTop);
  polBox->setLayout(polLayout);
 
  reset = new QPushButton("Reset");
  QVBoxLayout *buttons = new QVBoxLayout();
  buttons->addWidget(reset);

  QGridLayout *layout = new QGridLayout(this);
  layout->addWidget(nbLayer,0,0,1,1);
  layout->addLayout(layersLayout,1,0,1,1);
  layout->addLayout(buttons,2,0,1,1);
  layout->addWidget(materialBox,0,1,2,1);
  layout->addWidget(geometryBox,0,2,1,1);
  layout->addWidget(exchangeBox,1,2,1,1);
  layout->addWidget(demagnetizationBox,2,3,1,1);
  layout->addWidget(magnetizationBox,0,3,2,1);
  layout->addWidget(polBox,2,1,1,2);

  initializeWidgets();
  QObject::connect(nbLayer,SIGNAL(activated(int)),this,SLOT(disableLayers(int)));
  QObject::connect(layer1,SIGNAL(clicked()),this,SLOT(loadLayer()));
  QObject::connect(layer2,SIGNAL(clicked()),this,SLOT(loadLayer()));
  QObject::connect(layer3,SIGNAL(clicked()),this,SLOT(loadLayer())); 
  QObject::connect(layer1,SIGNAL(toggled(bool)),this,SLOT(saveLayer1()));
  QObject::connect(layer2,SIGNAL(toggled(bool)),this,SLOT(saveLayer2()));
  QObject::connect(layer3,SIGNAL(toggled(bool)),this,SLOT(saveLayer3())); 
  QObject::connect(reset,SIGNAL(clicked()),this,SLOT(resetParameters()));
  QObject::connect(polType,SIGNAL(activated(int)),polWidget,SLOT(setCurrentIndex(int)));
}

SampleWindow::~SampleWindow()
{

}

void SampleWindow::disableLayers(int choice)
{
  switch(choice)
    {
    case 0 : 
      {
	layer1->setDisabled(false);
	layer2->setDisabled(true);
	layer3->setDisabled(true);
	break;
      }
    case 2 :
      {
	layer1->setDisabled(false);
	layer2->setDisabled(false);
	layer3->setDisabled(false);
	break;
      }
    case 1 :
      {
	layer1->setDisabled(false);
	layer2->setDisabled(false);
	layer3->setDisabled(true);
	break;
      }
    }
}

void SampleWindow::resetParameters()
{
  clearParameters();
  tempParams = oldParams;
  loadLayer();
}

void SampleWindow::loadLayer()
{
  int layerNumber;
  if(layer1->isChecked())
    {
      layerNumber=0;
    }
  if(layer2->isChecked())
    {
      layerNumber=1;
    }
  if(layer3->isChecked())
    {
      layerNumber=2;
    }
  QString str;
  clearParameters();
  std::cout<<"Loading Layer "<<layerNumber<<std::endl;
  alpha->setValue(tempParams.getSample()[layerNumber]["alpha"]);
  ms->insert(str.setNum(tempParams.getSample()[layerNumber]["ms"]));
  surface->insert(str.setNum(tempParams.getSample()[layerNumber]["surface"]));
  thickness->insert(str.setNum(tempParams.getSample()[layerNumber]["thickness"]));
  k->insert(str.setNum(tempParams.getSample()[layerNumber]["k"]));
  kTheta->setValue(tempParams.getSample()[layerNumber]["aniTheta"]);
  kPhi->setValue(tempParams.getSample()[layerNumber]["aniPhi"]);
  mx->setValue(tempParams.getSample()[layerNumber]["mx"]);
  my->setValue(tempParams.getSample()[layerNumber]["my"]);
  mz->setValue(tempParams.getSample()[layerNumber]["mz"]);
  selfX->setValue(tempParams.getSample()[layerNumber]["ndx"]);
  selfY->setValue(tempParams.getSample()[layerNumber]["ndy"]);
  selfZ->setValue(tempParams.getSample()[layerNumber]["ndz"]);
  mutualX->setValue(tempParams.getSample()[layerNumber]["nrx"]);
  mutualY->setValue(tempParams.getSample()[layerNumber]["nry"]);
  mutualZ->setValue(tempParams.getSample()[layerNumber]["nrz"]);
  downExchange->insert(str.setNum(tempParams.getSample()[layerNumber]["downExchange"]));
  upExchange->insert(str.setNum(tempParams.getSample()[layerNumber]["upExchange"]));
  frozen->setChecked(tempParams.getSample()[layerNumber]["frozen"]);
  initialAngle->setValue(tempParams.getSample()[layerNumber]["initialAngle"]);
  polarization->setValue(tempParams.getSample()[layerNumber]["polarization"]);
  qplus->setValue(tempParams.getPolarization()["qplus"]);
  qminus->setValue(tempParams.getPolarization()["qminus"]);
  b0->setValue(tempParams.getPolarization()["b0"]);
  b1->setValue(tempParams.getPolarization()["b1"]);
  QString polChoice = tempParams.getPolarizationType();
  if(polChoice == "Slonczewski")
    {
      polType->setCurrentIndex(0);
      polWidget->setCurrentIndex(0);
    }
  else if(polChoice == "Xiao") 
    {
      polType->setCurrentIndex(1);
      polWidget->setCurrentIndex(1);
    }
}

void SampleWindow::saveLayer(int layerNumber)
{
  QMap<QString,double> Layer,Polarization;
  Layer["alpha"]=alpha->value();
  Layer["ms"]=ms->text().toFloat(); 
  Layer ["k"]=k->text().toFloat();
  Layer["aniPhi"]=kPhi->value();
  Layer["aniTheta"]=kTheta->value();
  Layer["thickness"]=thickness->text().toFloat();
  Layer["surface"]=surface->text().toFloat();
  Layer["upExchange"]=upExchange->text().toFloat();
  Layer["downExchange"]=downExchange->text().toFloat(); 
  Layer["mx"]=mx->value();  
  Layer["my"]=my->value();
  Layer["mz"]=mz->value();
  Layer["ndx"]=selfX->value();
  Layer["ndy"]=selfY->value();
  Layer["ndz"]=selfZ->value();
  Layer["nrx"]=mutualX->value();
  Layer["nry"]=mutualY->value();
  Layer["nrz"]=mutualZ->value();
  Layer["frozen"]=frozen->isChecked();
  Layer["initialAngle"]=initialAngle->value();
  Layer["polarization"] = polarization->value();
  Polarization["qplus"] = qplus->value();
  Polarization["qminus"] = qminus->value();
  Polarization["b0"] = b0->value();
  Polarization["b1"] = b1->value();
  QVector<QMap<QString,double> > tempSample;
  tempSample=tempParams.getSample();
  tempSample.replace(layerNumber,Layer);
  tempParams.setSample(tempSample);
  tempParams.setPolarization(Polarization);
  tempParams.setPolarizationType(polType->currentText());
}

void SampleWindow::saveLayer1()
{
  if(!layer1->isChecked())
    {
      saveLayer(0);
    }
}

void SampleWindow::saveLayer2()
{
  if(!layer2->isChecked())
    {
      saveLayer(1);
    }
}

void SampleWindow::saveLayer3()
{
  if(!layer3->isChecked())
    {
      saveLayer(2);
    }
}

void SampleWindow::clearParameters()
{
  k->clear();
  ms->clear();
  alpha->clear();
  thickness->clear();
  surface->clear();
  downExchange->clear();
  upExchange->clear();
  kPhi->clear();
  kTheta->clear();
  selfX->clear();
  selfY->clear();
  selfZ->clear();
  mutualX->clear();
  mutualY->clear();
  mutualZ->clear();
  mx->clear();
  my->clear();
  mz->clear();
  initialAngle->clear();
  polarization->clear();
  qminus->clear();
  qplus->clear();
  b0->clear();
  b1->clear();
}

NewParameters SampleWindow::getParameters(NewParameters params)
{
  layer1->click();
  layer2->click();
  //layer3->click();
  params.setSample(tempParams.getSample());
  params.setPolarization(tempParams.getPolarization());
  params.setPolarizationType(polType->currentText());
  return params;
}

void SampleWindow::initializeWidgets()
{
  mx->setRange(-1,1);
  mx->setSingleStep(0.01);
  mx->setDecimals(4);
  my->setRange(-1,1);
  my->setSingleStep(0.01);
  my->setDecimals(4);
  mz->setRange(-1,1);
  mz->setSingleStep(0.01);
  mz->setDecimals(4);
  kPhi->setRange(0,180);
  kTheta->setRange(0,180);
  alpha->setRange(0,1);
  alpha->setSingleStep(0.01);

}

void SampleWindow::loadParameters(NewParameters newParams)
{
  clearParameters(); 
  tempParams = newParams;
  oldParams = newParams;
  layer1->click();
}
